5. 打包发布
我们编写好了GUI应用后,还需要将其打包发布出去,给大家使用,这就涉及到桌面应用的打包知识了。对于桌面程序而言,打包发布是非常重要的环节,特单列一章阐述。
5.1 源码发布
通常来说,源码发布不是一个好主意!笔者工作中接触过一些测试部门的人员,其中一些测试人员由于自身水平的问题,只有半桶水,非常喜欢将自己编写的一些质量测试工具直接以Python源码的形式给到一线同事,一线同事并不太懂技术,往往折腾一上午环境安装,最后还是跑不起来。究其根本来说,就是不懂桌面程序的打包发布,而且往往还不能引起其重视。Python虽然是跨平台语言,但对于普通用户而言,直接获得源码并不能运行程序,第一步需要安装正确版本的Python解释器。Python不同版本的兼容性往往是个头疼的问题,除了众所周知的2.x和3.x兼容问题外,还有高版本新特性与低版本之间的兼容问题。没有一定的Python功力水平,写出的代码往往存在容易被忽视的兼容问题,源码在自己机器上可能运行良好,但是到了对方机器上,哪怕Python解释器版本相同,也有可能无法运行,这很可能是引用的第三方库版本兼容问题。
另外,这些半桶水的人有的还喜欢给编译后的pyc
文件,这简直就是灾难性的巨坑,你连源码也无法直接查看,完全不知道他的源码引用了哪些第三方库,就算是懂Python的人也没法迅速搭建好对应的环境。
基于以上这些坑,笔者不愿意介绍源码发布方法,包括编译pyc
,准备requirements.txt
文件等,相信会的人无需我来说,不会的我也不想介绍,以免坑人坑己,请大家理解。
5.2 py文件与pyw文件
通常python中的脚本文件都是.py
后缀格式,但如果编写的是tkinter
的图形程序,则应当以.pyw
格式为脚本后缀名。.pyw
格式与.py
最显著的区别是,运行前者不会生成一个黑框控制台,而是直接以图形界面程序运行。具体来说,pyw
格式有如下区别
- 运行时不会弹出控制台窗口(DOS 窗口)
- 所有向
stdout
和stderr
的输出都无效 - 所有从
stdin
的读取都只会得到EOF
5.3 打包成exe可执行程序
对于桌面程序而言,打包成exe
可执行程序是最好的方式。
5.3.1 安装 pyinstaller
将Python程序打包为exe
时,推荐使用pyinstaller
库,相对来说使用更简单,我们首先使用pip
来安装该库,如下
python -m pip install pyinstaller
如果大家网速不好,访问外网速度不给力,可以使用国内阿里的镜像,速度会很快,使用-i
指定镜像即可
python -m pip install pyinstaller -i http://mirrors.aliyun.com/pypi/simple/
特别注意
想在命令行运行pyinstaller
命令,需要配置环境变量,将pyinstaller.exe
加入到系统PATH
中,如同pip
命令一样,我非常不建议在Windows上配置大量命令,既然pyinstaller
是Python的一个第三方库,我们可以直接使用python命令加-m
参数去调用,但要注意,作为包名时,其首字母是大写的,因此调用方式如下
python -m PyInstaller
基本参数说明
-F
生成单个可执行文件
-w
禁用控制台窗口,不加该参数生成的GUI程序启动时,背后会有一个控制台黑窗口(类似
py
与pyw
的区别),建议添加该参数-i
为可执行程序指定一个
.ico
格式的小图标
5.3.2 打包为单 exe 程序
不论工程中引用了多少库,最终都只会压缩生成一个单独的
exe
文件
简单示例
我在D:\workspace\pythoncode
路径下创建了一个测试脚本 hello.py
则在命令行中cd
到该目录下,然后执行以下命令
python -m PyInstaller -F hello.py
执行完成后,会在该目录下生成一个dist
文件夹,里面放的就是hello.exe
示例只有一个脚本文件,如果你的工程中有多个python脚本文件,则应该在命令中指定入口脚本文件名。
指定小图标
如果我们想为窗口程序指定一个图标,则将相应的.ico
文件拷贝到当前目录下,添加-i
参数指定图标
python -m PyInstaller -F hello.py -i hello.ico
包含第三方库
如果我们的Python代码引用了第三方库,则需要拷贝相应的第三方库源码。
hello.py
代码如下,我们引用了爬虫中常用的requests
库
import requests
resp = requests.get("https://www.baidu.com/")
print(resp.content)
则需要拷贝一份requests
库源码到当前打包的目录下,进入到Python安装的根目录,然后进到\Lib\site-packages
下,我们知道,site-packages
文件夹就是用来存放所有已安装的第三方库的,在其下找到我们引用的第三方库文件夹,如上例中的requests
,将整个文件夹拷贝至打包的项目根路径下,最后再执行上述的打包命令打包即可。
5.3.3 打成多文件包
将整个工程打包成一个单独exe
文件后,程序的启动速度会明显变慢。如果希望我们自己的程序启动快速,有良好的用户体验,则应该将工程打成多文件包,只需要在上述打包命令中去除-F
参数即可。
以上示例打包后,会在dist
文件夹下生成hello
文件夹,文件夹中会产生非常多的文件,包含dll
、pyd
文件等等。对于普通用户而言,这样的包是非常不友好的,进入到文件夹后会有发懵的感觉,不知道到底从哪里启动程序。实际上,在hello
文件夹中,仍然有一个hello.exe
文件,它就是启动程序。
5.3.4 制作安装包
打成多文件包可以让程序启动更加快速,但是生成太多文件,又会让普通用户感到困惑,降低用户体验。实际上,想要解决这个问题,大多数商业软件都是将多文件包制作成安装包的形式,用户启动安装包后,会将我们的多文件包解压到指定文件夹,然后还会生成桌面快捷方式,自动卸载程序等。
制作安装包其实不难,我们首先需要下载NSIS
工具
下载并安装好NSIS
后,需要编写NIS
脚本来制作安装包,仅仅制作安装包,没有必要去学习这种脚本,因此我们还需要下载一个工具,来自动生成NIS
脚本,它就是NIS EDIT
下载并安装好NIS EDIT
后,按照上述的命令,将Python程序打成多文件包,然后按照以下步骤生成NIS
脚本文件
打开
NIS EDIT
,选择【新建脚本:向导】填写应用信息。主要是应用名和版本号
设置应用的
Icon
图标。选择准备好的ico格式图标,并为安装器起一个有意义的名字,语言则选择简体中文,要去除English的勾选。创建授权文件并指定。我这里事先创建了一个叫
SoftwareLicence.txt
的文件,内容请根据实际编写许可协议 这是许可协议,默认你同意一切条款,关于该协议的所有条款的解释权归本公司所有。
添加我们之前已经打包好的多文件包目录
依次下一步
选择我们多文件包中的启动程序
配置卸载程序
选中如下三项,完成后,弹出另存为对话框,为我们生成的
.nsi
脚本起一个名字,保存后,该脚本将开始自动编译,编译完成后,在脚本同级目录下,会生成安装器程序hello-Setup.exe
,将安装器程序发布出去即可。